#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import glob
import json
import os

from common.common import get_host_sn
from exchange.commons.common import read_file
from exchange.commons.const import RepositoryDataTypeEnum, CopyDataTypeEnum


class RestoreParamParser:
    @staticmethod
    def get_copy_database_name(json_param: dict):
        """
        获取备份副本的数据库名称
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("extendInfo", {}).get("db_name")

    @staticmethod
    def get_exchange_server_version(json_param: dict):
        """
        获取备份时exchange server 版本
        :param json_param:
        :return:
        """
        if json_param.get("job", {}).get("copies")[0].get("type", {}) in [CopyDataTypeEnum.S3_ARCHIVE.value,
                                                                          CopyDataTypeEnum.TAP_ARCHIVE]:
            # 归档副本的扩展信息多嵌套了一层
            return json_param.get("job", {}).get("copies")[0].get("extendInfo", {}).get("extendInfo", {}).get("version")
        return json_param.get("job", {}).get("copies")[0].get("extendInfo", {}).get("version")

    @staticmethod
    def get_copy_exchange_server_name(json_param: dict):
        """
        获取备份时exchange server name
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("extendInfo", {}).get(
            "server_name")

    @staticmethod
    def get_copy_exchange_edb_path_and_log_path(json_param: dict):
        """
        获取备份时exchange server name
        :param json_param:
        :return:
        """
        edb_path = json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("extendInfo", {}).get(
            "edb_path")
        log_path = json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("extendInfo", {}).get(
            "log_path")
        return edb_path, log_path

    @staticmethod
    def get_exchange_database_guid(json_param: dict):
        """
        获取数据库guid
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("extendInfo", {}).get("db_uuid")

    @staticmethod
    def get_exchange_database_copy_repo(json_param: dict):
        """
        获取数据仓信息
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies", [])[0].get("repositories", [])

    @staticmethod
    def get_exchange_database_copy_repo_for_log(json_param: dict):
        """
        获取日志仓信息
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies", [])[-1].get("repositories", [])

    @staticmethod
    def get_copy_nodes_list(json_param: dict):
        """
        获取恢复节点信息
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectEnv", {}).get("nodes")

    @staticmethod
    def get_copy_agent_id(json_param: dict):
        """
        获取副本备份时agentId
        :param json_param:
        :return:
        """
        # 根据备份时的服务名，和节点信息获取备份时agent_id
        nodes_list = RestoreParamParser.get_copy_nodes_list(json_param)
        server_name = RestoreParamParser.get_copy_exchange_server_name(json_param)
        agent_id = None
        for node in nodes_list:
            if server_name.lower() == node.get("name").lower():
                agent_id = node.get("id")
                break
        return agent_id

    @staticmethod
    def get_restore_target_type(json_param: dict):
        """
        获取恢复目标类型: 单机/DAG组
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("targetEnv", {}).get("extendInfo", {}).get("isGroup", "")

    @staticmethod
    def get_restore_nodes_list(json_param: dict):
        """
        获取恢复节点信息
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("targetEnv", {}).get("nodes", [])

    @staticmethod
    def get_restore_resource_sub_type(json_param: dict):
        """
        获取恢复资源子类型
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("subType")

    @staticmethod
    def get_auto_dismount(json_param: dict):
        """
        获取自动卸载参数
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("auto_dismount", str)

    @staticmethod
    def get_auto_mount(json_param: dict):
        """
        获取自动装载参数
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("auto_mount", str)

    @staticmethod
    def get_target_database_log_path(json_param: dict):
        """
        获取目标位置数据日志路径
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("target_db_log_path", "")

    @staticmethod
    def get_target_database_edb_path(json_param: dict):
        """
        获取目标位置数据数据路径
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("target_db_data_path", "")

    @staticmethod
    def get_restore_location(json_param: dict):
        """
        获取恢复位置类型
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("restore_location", str)

    @staticmethod
    def get_restore_new_database_name(json_param: dict):
        """
        获取恢复位置类型
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("new_db_name", str)

    @staticmethod
    def get_target_restore_database_name(json_param: dict):
        """
        获取恢复目标数据库名称
        :return:
        """
        database_name = RestoreParamParser.get_copy_database_name(json_param)
        new_database_name = RestoreParamParser.get_restore_new_database_name(json_param)
        return database_name if database_name == new_database_name else new_database_name

    @staticmethod
    def get_target_restore_database_name_and_new_name(json_param: dict):
        """
         获取恢复目标数据库名称,dag 或是 单机细粒度恢复解析数据库名用
         :return:
        """
        restore_objects = json_param.get("job", {}).get("restoreSubObjects", [])
        result = []
        for restore_object in restore_objects:
            database_name = json.loads(restore_object['extendInfo']['databaseName'].replace("'", "\""))
            source_db_name = database_name['source_db_name']
            source_target_name = database_name['source_target_name']
            result.append({'source_db_name': source_db_name, 'source_target_name': source_target_name})
        return result

    @staticmethod
    def get_protect_server_resource_id(json_param: dict):
        """
        获取数据库guid
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("protectObject", {}).get("id", "")

    @staticmethod
    def get_dag_exchange_server_version(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[0].get("extendInfo", {}).get("version")

    @staticmethod
    def get_single_copy_agent_id(json_param: dict):
        """
        获取副本备份时agentId
        :param json_param:
        :return:
        """
        # 根据备份时的服务名，和节点信息获取备份时agent_id
        nodes_list = RestoreParamParser.get_copy_nodes_list(json_param)
        agent_id = None
        for node in nodes_list:
            agent_id = node.get("id")
            break
        return agent_id

    @staticmethod
    def get_restore_job_type(json_param: dict):
        """
        获取恢复任务类型
        :param json_param: 任务参数
        :return: 任务类型
        """
        return json_param.get("job", {}).get("jobParam", {}).get("restoreType", str)

    @staticmethod
    def get_fine_grained_restore_objects(json_param: dict):
        """
        获取细粒度恢复的对象
        :param json_param: 任务参数
        :return: 细粒度恢复的对象
        """
        return json_param.get("job", {}).get("restoreSubObjects")

    @staticmethod
    def get_copy_size(json_param: dict):
        """
        获取副本大小
        :param json_param: 任务参数
        :return: 副本大小，单位为KB
        """
        return json_param.get("job", {}).get("copies", {})[0].get("extendInfo", "").get("dataBeforeReduction", 0)

    @staticmethod
    def get_data_restore_repositories_meta_path(json_param: dict):
        """
        恢复场景获取meta仓
        :param json_param:
        :return:
        """
        repositories = json_param.get("job", {}).get("copies", [])[-1].get("repositories", [])
        data_meta_path = ""
        for repository in repositories:
            if repository.get("repositoryType") == RepositoryDataTypeEnum.META_REPOSITORY.value:
                data_meta_path = repository.get("path", [""])[0]
        return data_meta_path

    @staticmethod
    def get_data_restore_repositories_data_path(json_param: dict):
        """
        恢复场景获取data仓
        :param json_param:
        :return:
        """
        repositories = json_param.get("job", {}).get("copies", [])[0].get("repositories", [])
        data_meta_path = ""
        for repository in repositories:
            if repository.get("repositoryType") == RepositoryDataTypeEnum.DATA_REPOSITORY.value:
                data_meta_path = repository.get("path", [""])[0]
        return data_meta_path

    @staticmethod
    def get_restore_type(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies")[-1].get("type", "")

    @staticmethod
    def get_restore_time_stamp(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("extendInfo", {}).get("restoreTimestamp", "")

    @staticmethod
    def get_log_restore_repositories(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        return json_param.get("job", {}).get("copies", [])[-1].get("repositories", [])

    @staticmethod
    def get_log_restore_repositories_log_path(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        repositories = json_param.get("job", {}).get("copies", [])[-1].get("repositories", [])
        log_mount_path = ""
        copy_id = json_param.get("job").get("copies")[-1].get("id")
        for repository in repositories:
            if repository.get("repositoryType") == RepositoryDataTypeEnum.LOG_REPOSITORY.value:
                log_mount_path = repository.get("path", [""])[0]
                if copy_id in log_mount_path:
                    break
        return log_mount_path

    @staticmethod
    def get_log_restore_repositories_log_paths(json_param: dict):
        """
        获取备份时exchange dag server 版本
        :param json_param:
        :return:
        """
        repositories = json_param.get("job", {}).get("copies", [])[-1].get("repositories", [])
        log_mount_paths = []
        for repository in repositories:
            if repository.get("repositoryType") == RepositoryDataTypeEnum.LOG_REPOSITORY.value:
                log_mount_paths.append(repository.get("path", [""])[0])
        return log_mount_paths

    @staticmethod
    def get_database_name_maps(json_param: dict):
        if RestoreParamParser.get_restore_type(json_param) == CopyDataTypeEnum.LOG_COPY:
            # 取备份数据库新旧名称映射
            database_name_maps = RestoreParamParser.get_log_database_names_maps(json_param)
        elif RestoreParamParser.get_restore_type(json_param) == CopyDataTypeEnum.S3_ARCHIVE or RestoreParamParser. \
                get_restore_type(json_param) == CopyDataTypeEnum.TAP_ARCHIVE:
            # 归档副本取备份数据库新旧名称映射
            database_name_maps = RestoreParamParser.get_archive_database_names_maps(json_param)
        else:
            database_name_maps = RestoreParamParser.get_target_restore_database_name_and_new_name(json_param)
        return database_name_maps

    @staticmethod
    def get_database_names_maps(json_param: dict):
        log_mount_path = RestoreParamParser.get_log_restore_repositories_log_path(json_param)
        db_name_prefix, db_name_suffix = RestoreParamParser.get_db_name_prefix_and_suffix(json_param)
        metadata_path = os.path.join(log_mount_path, "database_name_dict")
        database_name_dict = read_file(metadata_path)
        database_name_list = database_name_dict["name_list"]
        database_name_maps = []
        for database_name in database_name_list:
            database_name_map = {"source_db_name": database_name, "source_target_name": database_name}
            if db_name_prefix:
                database_name_map["source_target_name"] = db_name_prefix + "_" + database_name_map.get(
                    "source_target_name")
            if db_name_suffix:
                database_name_map["source_target_name"] = database_name_map.get(
                    "source_target_name") + "_" + db_name_suffix
            database_name_maps.append(database_name_map)
        return database_name_maps

    @staticmethod
    def get_log_database_names_maps(json_param: dict):
        archive_meta_path = RestoreParamParser.get_log_restore_repositories_log_path(json_param)
        db_name_prefix, db_name_suffix = RestoreParamParser.get_db_name_prefix_and_suffix(json_param)
        result = RestoreParamParser.get_target_restore_database_name_and_new_name(json_param)
        db_name = ""
        if result:
            db_name = result[0].get("source_db_name")
        database_name_maps = []
        meta_files = glob.glob(os.path.join(archive_meta_path, "*.meta"))
        for file in meta_files:
            if db_name and db_name not in file:
                continue
            database_name = os.path.splitext(os.path.basename(file))[0]
            database_name_map = {"source_db_name": database_name, "source_target_name": database_name}
            if db_name_prefix:
                database_name_map["source_target_name"] = db_name_prefix + "_" + database_name_map.get(
                    "source_target_name")
            if db_name_suffix:
                database_name_map["source_target_name"] = database_name_map.get(
                    "source_target_name") + "_" + db_name_suffix
            database_name_maps.append(database_name_map)
        return database_name_maps

    @staticmethod
    def get_archive_database_names_maps(json_param: dict):
        archive_meta_path = RestoreParamParser.get_data_restore_repositories_meta_path(json_param)
        db_name_prefix, db_name_suffix = RestoreParamParser.get_db_name_prefix_and_suffix(json_param)
        database_name_maps = []
        meta_files = glob.glob(os.path.join(archive_meta_path, "*.meta"))
        for file in meta_files:
            database_name = os.path.splitext(os.path.basename(file))[0]
            database_name_map = {"source_db_name": database_name, "source_target_name": database_name}
            if db_name_prefix:
                database_name_map["source_target_name"] = db_name_prefix + "_" + database_name_map.get(
                    "source_target_name")
            if db_name_suffix:
                database_name_map["source_target_name"] = database_name_map.get(
                    "source_target_name") + "_" + db_name_suffix
            database_name_maps.append(database_name_map)
        return database_name_maps

    @staticmethod
    def get_current_node_endpoint(json_param: dict):
        """
        查询当前节点ip
        :param json_param:
        :return:
        """
        ip = ""
        for node in json_param.get("job").get("targetEnv").get("nodes"):
            if get_host_sn() == node['id']:
                ip = node['endpoint']
        return ip

    @staticmethod
    def get_db_name_prefix_and_suffix(json_param: dict):
        db_name_prefix = json_param.get("job", {}).get("extendInfo", {}).get("db_name_prefix", "")
        db_name_suffix = json_param.get("job", {}).get("extendInfo", {}).get("db_name_suffix", "")
        return db_name_prefix, db_name_suffix

    @staticmethod
    def get_copy_meta_data_info(source_name, json_param):
        restore_type = RestoreParamParser.get_restore_type(json_param)
        if restore_type == CopyDataTypeEnum.LOG_COPY:
            repositories = RestoreParamParser.get_exchange_database_copy_repo_for_log(json_param)
        else:
            repositories = RestoreParamParser.get_exchange_database_copy_repo(json_param)
        copy_id = json_param.get("job").get("copies")[-1].get("id")
        for repository in repositories:
            repository_type = repository.get("repositoryType")
            mount_path = repository.get("path")[0]
            if restore_type == CopyDataTypeEnum.LOG_COPY:
                if repository_type == RepositoryDataTypeEnum.LOG_REPOSITORY.value and copy_id in mount_path:
                    break
            else:
                if repository_type == RepositoryDataTypeEnum.META_REPOSITORY.value:
                    break
        metadata_path = os.path.join(mount_path, f"{source_name}.meta")
        copy_meta_data = read_file(metadata_path)
        return copy_meta_data

    @staticmethod
    def get_backup_copy_agent_id(json_param: dict):
        """
        获取备份时的agent_id,即客户端的host_sn
        :param json_param:
        :return: agent_id
        """
        db_name = RestoreParamParser.get_copy_database_name(json_param)
        copy_meta_data = RestoreParamParser.get_copy_meta_data_info(db_name, json_param)
        return copy_meta_data.get("agentId")
